简体   繁体   English

将多张照片上传(并重命名)到服务器

[英]Upload (and rename) several photos to the server

Even if I am not good in development, I am trying to create a form which allows to upload several photos to the server and text to the database.即使我不擅长开发,我也在尝试创建一个表单,允许将多张照片上传到服务器并将文本上传到数据库。

For the text, no problem.对于文本,没有问题。 To upload ONE photo too, that's doing it well.也上传一张照片,这很好。

What I can't do is upload SEVERAL photos in a single form submission.我不能做的是在一个表单提交中上传几张照片。 Should I use a while or for or foreach loop?我应该使用while还是forforeach循环? If so, how do I retrieve the photos informations?如果是这样,我如何检索照片信息? I specify that I'm not trying to use the "Multiple" function.我指定我不会尝试使用“多个”function。 Even if the files are uploaded in the same form, the user must use separate "File upload" fields.即使文件以相同的形式上传,用户也必须使用单独的“文件上传”字段。

I specify that I want to rename the files during the upload.我指定要在上传期间重命名文件。 With the code below, the upload works but only the renaming of the first file works.使用下面的代码,上传工作,但只有第一个文件的重命名工作。 The second (and surely the following ones too) are badly renamed.第二个(当然还有以下几个)被严重重命名。 Example for the second:第二个例子:

78_One Plus_Nouveau test_FaceProduct_ pic03.jpgpic04.jpg 78_One Plus_Nouveau test_FaceProduct_pic03.jpgpic04.jpg

I would to have some help to create a loop for upload images process and rename correctly the image files please?我需要一些帮助来创建上传图像过程的循环并正确重命名图像文件吗?

    error_reporting(E_ALL);

// Then retrieve all the other information from the form: 
$productname = isset($_POST['productname']) ? $_POST['productname'] : NULL;
$productbrand = isset($_POST['productbrand']) ? $_POST['productbrand'] : NULL;
$addername = isset($_POST['addername']) ? $_POST['addername'] : NULL;
$adderemail = isset($_POST['adderemail']) ? $_POST['adderemail'] : NULL;

// paramètres de connexion
$cbnserver = "xxxxxx";
$cbnuser = "xxxxxxxxx";
$cbnpass = "xxxxxxxxx";
$cbndbname = "xxxxxxxxxxxxx";

// Requête d'insertion dans la base
$dbco = new PDO("mysql:host=$cbnserver;dbname=$cbndbname", $cbnuser, $cbnpass);
$dbco->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$req = $dbco->prepare('INSERT INTO `cbnadd_newproduct` (productname, productbrand, addername, adder_email) VALUES(:productname,:productbrand,:addername,:adder_email)');
$req->execute(array(
 'productname' => $productname,
 'productbrand' => $productbrand,
 'addername' => $addername,
 'adder_email' => $adderemail
 ));
$lineid = $dbco->lastInsertId() ;


// Designate the directory where the images will be saved with this code:
$targetFA = "images/". $lineid ."_". $productbrand ."_". $productname ."_FaceProduct_";
$targetFA = $targetFA . basename( $_FILES['photoFA']['name']); 
$targetNV = "images/". $lineid ."_". $productbrand ."_". $productname ."_FaceProduct_";
$targetNV = $targetFA . basename( $_FILES['photoNV']['name']); 


// This writes the photo to the server 
$namefileFA = basename( $_FILES['photoFA']['name']);
$namefileFA = $lineid ."_". $productbrand ."_". $productname ."_". $namefileFA;
$namefileNV = basename( $_FILES['photoFA']['name']);
$namefileNV = $lineid ."_". $productbrand ."_". $productname ."_". $namefileNV;

if(move_uploaded_file($_FILES['photoFA']['tmp_name'],$targetFA) & move_uploaded_file($_FILES['photoNV']['tmp_name'],$targetNV)) { 

 // This code tells you if it is all ok or not.
 echo "<br><br>The file ". $namefileFA. " and has been uploaded, and your information has been added to the directory<br>"; 
 echo "<br><br>The file ". $namefileNV. " has been uploaded, and your information has been added to the directory<br>"; 

} else {
 echo "<br><br>Sorry, there was a problem uploading your file."; 
}

Here the HTML code for the photo fields:这里是照片字段的 HTML 代码:

<form enctype="multipart/form-data" action="../add.php" method="POST"> 

<!--Product Name: --><input type="text" name="productname"><br>
<h3>Brand</h3>
<!--Brand: --><input type="text" name = "productbrand"><br>

Importer les photos du produit: 
<label for="fileFA" class="label-file" style="cursor:pointer; color:#00b1ca; font-weight:bold;">Couverture/face du produit</label>
<input id="fileFA" class="input-file" type="file" name="photoFA" style="display: none;">
<!--<input type="file" name="photo"><br>-->
<label for="fileNV" class="label-file" style="cursor:pointer; color:#00b1ca; font-weight:bold;">Tableau nutritionnel du produit</label>
<input id="fileNV" class="input-file" type="file" name="photoNV" style="display: none;">
Your name: <input type="text" name = "addername"><br> 
Adder email: <input type="text" name = "adderemail"><br>                                    
<input type="submit" value="Add" class="centered">      
</form>

Thank you @Professor I create the table, tested the page but two things are strange:谢谢@Professor 我创建了表格,测试了页面,但有两件事很奇怪:

  1. There's a problem with the messages, the name of the photo doesn't appear.消息有问题,照片的名称没有出现。
  2. And even if I insert ONE photo the system update 4 lines on database.即使我插入一张照片,系统也会在数据库中更新 4 行。

Here the messages I got:这是我收到的消息:

The file "130_Candy_Produit_FaceProduct_pic01.jpg" has been uploaded OK.文件“130_Candy_Produit_FaceProduct_pic01.jpg”已上传成功。 Information has been added to the directory: True There was a problem saving "130_Candy_Produit_NutritionValue_".信息已添加到目录中:True 保存“130_Candy_Produit_NutritionValue_”时出现问题。 Information logged to db: True There was a problem saving "130_Candy_Produit_Ingredients_".记录到 db 的信息:True 保存“130_Candy_Produit_Ingredients_”时出现问题。 Information logged to db: True There was a problem saving "130_Candy_Produit_Labels_".记录到 db 的信息:True 保存“130_Candy_Produit_Labels_”时出现问题。 Information logged to db: True记录到 db 的信息:真

And here the code:这里的代码:

    error_reporting( E_ALL );
    
    class PostException extends Exception {
        public function __construct( $msg=null, $code=null ){
            parent::__construct( $msg, $code );
        }
        public function geterror(){
            return $this->getMessage();
        }
    }
    
    if( $_SERVER['REQUEST_METHOD']=='POST' ){
        try{
        
            #look at the form - see how it is using this for image name
            $field='productimage';

            if( isset(
                $_FILES[ $field ],
                $_POST['productname'],
                $_POST['productbrand'],
                $_POST['addername'],
                $_POST['adder_email']
            ) ){                                        
                $errors=array();
                $uploads=array();
                $files=array();
                $lineid=false;
                $dbstatus=false;                    
                
                #################################
                # edit this as appropriate...
                $dir=__DIR__ . '/imagesStack';

                
                
                # the names of the various fields in the form - not images
                $args=array(
                    'productname',
                    'productbrand',
                    'addername',
                    'adder_email'
                );
                /*
                    loop through the `$args` array - if a field in the FORM
                    is not set or empty throw & catch a custom exception - 
                    the errors will be displayed later.
                    
                    If no errors, generate the variables based upon the name of
                    the field using variable variables.
                */
                foreach( $args as $fieldname ){
                    try{
                        if( !isset( $_POST[ $fieldname ] ) or empty( $_POST[ $fieldname ] ) )throw new PostException( sprintf( 'Missing data: The field "%s" is required.', $fieldname ) );
                        else{
                            ${$fieldname}=$_POST[ $fieldname ];
                        }
                    }catch( PostException $e ){
                        $errors[]=$e->geterror();
                        continue;
                    }
                }
                
                if( empty( $errors ) ){
                    $args=array(
                        'host'  =>  'localhost',
                        'user'  =>  'FFFFF',
                        'pwd'   =>  'EEEEEEEE',
                        'db'    =>  'GGGGGGGGGG'
                    );
                    mysqli_report( MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT );
                    $db=new mysqli( ...array_values( $args ) );
                    $db->set_charset('utf8');
                    $db->begin_transaction();
                    
                    
                    #create the basic sql and prepared statement
                    $sql='insert into `cbnadd_newproduct` 
                            ( `productname`, `productbrand`, `addername`, `adder_email` )
                        values
                            ( ?,?,?,? )';
                    $stmt=$db->prepare( $sql );
                    
                    
                    /* bind params and execute */
                    $stmt->bind_param('ssss', $productname, $productbrand, $addername, $adder_email );
                    $dbstatus=$stmt->execute();
                    
                    /* get the ID of the last inserted record */
                    $lineid=$db->insert_id;
                    $stmt->close();
                            
                    /*
                        It would be usual to record the names / paths of images
                        that you upload so I created a new table for that purpose
                    */
                    # insert records for new images to other table.
                    $sql='insert into `cbnadd_productimages` (`lineid`,`image`) values (?,?)';
                    $stmt=$db->prepare( $sql );
                    $stmt->bind_param('is', $lineid, $targetname );                    
                    
                    
                    /*
                        Process the file uploads - using the Array syntax 
                        means you can easily loop through all the files &
                        rename and log to db.
                    */
                    $obj=$_FILES[ $field ];
                    foreach( $obj['name'] as $index => $void ){
                        
                        $name=$obj['name'][ $index ];
                        $tmp=$obj['tmp_name'][ $index ];
                        
                        # new image name format "id_brand_product_category_filename.ext"
                        $targetname=sprintf('%d_%s_%s_%s_%s', $lineid, $productbrand, $productname, $index, $name );
                        
                        # full path for the image to be saved to
                        $targetpath=sprintf('%s/%s', $dir, $targetname );
                        
                        # move the file
                        $status=move_uploaded_file( $tmp, $targetpath );
                        
                        # upload the output variable
                        $uploads[]=$status ? sprintf('The file "%s" has been uploaded OK. Information has been added to the directory: %s', $targetname, ( $dbstatus ? 'True' : 'False' ) ) : sprintf('There was a problem saving "%s". Information logged to db: %s ',$targetname, ( $dbstatus ? 'True' : 'False' ) );
                        
                        # maintain a list of files to be used if db operation fails.
                        $files[]=$targetpath;
                        
                        
                        
                        # save image details... or try to
                        $stmt->execute();
                    }
                    
                    
                    
                    #commit to database or erase files if there is a problem
                    if( !$db->commit() ) {
                        $errors[]='Failed to commit transaction';
                        foreach( $files as $file ){
                            unlink( $file );
                            $errors[]=sprintf('File deleted: "%s"',$file);
                        }
                        $uploads=[];
                    }

                }
            }
        }catch( Exception $e ){
            $errors[]=$e->getMessage();
        }
    }
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <title>PHP: Multiple file uploads - different inputs</title>
        <meta charset='utf-8' />
        <style>
            form{width:60%;float:none;margin:1rem auto;padding:0.5rem 1rem;font-family:monospace;border:1px dashed gray;border-radius:0.5rem;background:whitesmoke;}
            label{width:80%;margin:0.5rem auto;display:block;float:none;padding:0.25rem;}
            label > input{float:right;width:75%;}
            fieldset{margin:1rem auto;padding:1rem;border:1px solid rgba(100,100,100,0.5);background:white;border-radius:0.5rem;}
            form > div{margin:1rem auto}
            [type='submit']{padding:1rem;}
            legend{background:rgba(100,100,100,0.5);color:white;padding:0.5rem;border-radius:0.5rem;min-width:20%;}     
            
            .error{color:red;}
            .success{color:green;}
        </style>
    </head>
    <body>
        <form name='uploads' method='post' enctype='multipart/form-data'>
            
            <fieldset>
                <legend>Product</legend>
                <label>Name:<input type='text' name='productname' /></label>
                <label>Brand:<input type='text' name='productbrand' /></label>
            </fieldset>
            
            <fieldset>
                <legend>Product images</legend>
                <label>Image-Face:<input type='file' name='productimage[FaceProduct]' /></label>
                <label>Image-Nutrition:<input type='file' name='productimage[NutritionValue]' /></label>
                <!-- other images could be added using same method but different index values ~ EG: -->
                <label>Image-Ingredients:<input type='file' name='productimage[Ingredients]' /></label>
                <label>Image-Labels:<input type='file' name='productimage[Labels]' /></label>
            </fieldset>
            
            <fieldset>
                <legend>User details</legend>
                <label>Added by:<input type='text' name='addername' /></label>
                <label>Email:<input type='text' name='adder_email' /></label>
            </fieldset>
            
            <fieldset>
                <input type='submit' />
            </fieldset>
            
            <div>
            <?php
                if( $_SERVER['REQUEST_METHOD']=='POST' ){
                    if( !empty( $uploads ) ){
                        foreach( $uploads as $message )printf('<div class="success">%s</div>',$message);
                    }
                    if( !empty( $errors ) ){
                        foreach( $errors as $message )printf('<div class="error">%s</div>',$message);
                    }
                }
            ?>
            </div>
        </form>
    </body>
</html>

I put this demo together that shows how you might use a different naming convention in the HTML and tie that in with an array when processing the uploads with PHP.我把这个演示放在一起,展示了如何在 HTML 中使用不同的命名约定,并在使用 PHP 处理上传时将其与数组绑定。 If you look at the form - particularly the file inputs you will note a common name productimage but written in array syntax like productimage[ KEY ] - that allows access to KEY in the PHP whilst in the loop as you will see in the processing portion below.如果您查看表单 - 特别是file输入,您会注意到一个通用名称productimage但以数组语法(如productimage[ KEY ]编写 - 允许在循环中访问 PHP 中的KEY ,正如您将在下面的处理部分中看到的那样. This was written for mysqli but will be straightforward to migrate to PDO.这是为mysqli编写的,但可以直接迁移到 PDO。

There are plenty of comments throughout to help guide you - but you can test just by editing the db connection details and the $dir variable.整个过程中有很多注释可以帮助指导您 - 但您可以通过编辑 db 连接详细信息和$dir变量来进行测试。

<?php
    error_reporting( E_ALL );
    
    if( $_SERVER['REQUEST_METHOD']=='POST' ){
        
        class PostException extends Exception {
            public function __construct( $msg=null, $code=null ){
                parent::__construct( $msg, $code );
            }
            public function geterror(){
                return $this->getMessage();
            }
        }   

        try{
        
            #look at the form - see how it is using this for image name
            $field='productimage';

            if( isset(
                $_FILES[ $field ],
                $_POST['productname'],
                $_POST['productbrand'],
                $_POST['addername'],
                $_POST['adder_email']
            ) ){
                $errors=array();
                $uploads=array();
                $files=array();
                $lineid=false;
                $dbstatus=false;
                
                
                #################################
                # edit this as appropriate...
                $dir=__DIR__ . '/images/uploads';

                
                
                # the names of the various fields in the form - not images
                $args=array(
                    'productname',
                    'productbrand',
                    'addername',
                    'adder_email'
                );
                /*
                    loop through the `$args` array - if a field in the FORM
                    is not set or empty throw & catch a custom exception - 
                    the errors will be displayed later.
                    
                    If no errors, generate the variables based upon the name of
                    the field using variable variables.
                */
                foreach( $args as $fieldname ){
                    try{
                        if( !isset( $_POST[ $fieldname ] ) or empty( $_POST[ $fieldname ] ) ){
                            throw new PostException( sprintf( 'Missing data: The field "%s" is required.', $fieldname ) );
                        } else {
                            ${$fieldname}=$_POST[ $fieldname ];
                        }
                    }catch( PostException $e ){
                        $errors[]=$e->geterror();
                        continue;
                    }
                }
                
                
                
                
                if( empty( $errors ) ){
                    # -------------------------------------------------
                    # ignore the fact that this is a mysqli connection
                    # the same methodology will work with PDO so you 
                    # will need to use your own PDO connection
                    # OR
                    # edit the connection details below to suit
                    # -------------------------------------------------
                    $args=array(
                        'host'  =>  'localhost',
                        'user'  =>  'root',
                        'pwd'   =>  'xxx',
                        'db'    =>  'xxx'
                    );
                    mysqli_report( MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT );
                    $db=new mysqli( ...array_values( $args ) );
                    $db->set_charset('utf8');
                    $db->begin_transaction();
                    
                    
                    
                    /*
                        create table `cbnadd_newproduct` (
                            `id` int(10) unsigned not null auto_increment,
                            `productname` varchar(50) null default null,
                            `productbrand` varchar(50) null default null,
                            `addername` varchar(50) null default null,
                            `adder_email` varchar(50) null default null,
                            primary key (`id`)
                        )
                        collate='utf8mb4_general_ci'
                        engine=innodb;

                        +--------------+------------------+------+-----+---------+----------------+
                        | Field        | Type             | Null | Key | Default | Extra          |
                        +--------------+------------------+------+-----+---------+----------------+
                        | id           | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
                        | productname  | varchar(50)      | YES  |     | NULL    |                |
                        | productbrand | varchar(50)      | YES  |     | NULL    |                |
                        | addername    | varchar(50)      | YES  |     | NULL    |                |
                        | adder_email  | varchar(50)      | YES  |     | NULL    |                |
                        +--------------+------------------+------+-----+---------+----------------+
                    */
                    
                    #create the basic sql and prepared statement
                    $sql='insert into `cbnadd_newproduct` 
                            ( `productname`, `productbrand`, `addername`, `adder_email` )
                        values
                            ( ?,?,?,? )';
                    $stmt=$db->prepare( $sql );
                    
                    
                    /* bind params and execute */
                    $stmt->bind_param('ssss', $productname, $productbrand, $addername, $adder_email );
                    $dbstatus=$stmt->execute();
                    
                    /* get the ID of the last inserted record */
                    $lineid=$db->insert_id;
                    $stmt->close();
                            

                            
                            
                            
                            
                    /*
                        create table `cbnadd_productimages` (
                            `id` int(10) unsigned not null auto_increment,
                            `lineid` int(10) unsigned not null,
                            `image` varchar(128) not null,
                            primary key (`id`),
                            index `lineid` (`lineid`)
                        )
                        collate='utf8mb4_general_ci'
                        engine=innodb;
                        
                        +--------+------------------+------+-----+---------+----------------+
                        | Field  | Type             | Null | Key | Default | Extra          |
                        +--------+------------------+------+-----+---------+----------------+
                        | id     | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
                        | lineid | int(10) unsigned | NO   | MUL | NULL    |                |
                        | image  | varchar(128)     | NO   |     | NULL    |                |
                        +--------+------------------+------+-----+---------+----------------+
                        
                    */
                    /*
                        It would be usual to record the names / paths of images
                        that you upload so I created a new table for that purpose
                    */
                    # insert records for new images to other table.
                    $sql='insert into `cbnadd_productimages` (`lineid`,`image`) values (?,?)';
                    $stmt=$db->prepare( $sql );
                    $stmt->bind_param('is', $lineid, $targetname );
                    
                    
                    
                    /*
                        Process the file uploads - using the Array syntax 
                        means you can easily loop through all the files &
                        rename and log to db.
                    */
                    $obj=$_FILES[ $field ];
                    foreach( $obj['name'] as $index => $void ){
                        
                        $name=$obj['name'][ $index ];
                        $tmp=$obj['tmp_name'][ $index ];
                        
                        # ensure we don't process non-existant files
                        if( !empty( $tmp ) ){
                        
                            # new image name format "id_brand_product_category_filename.ext"
                            $targetname=sprintf('%d_%s_%s_%s_%s', $lineid, $productbrand, $productname, $index, $name );
                            
                            # full path for the image to be saved to
                            $targetpath=sprintf('%s/%s', $dir, $targetname );
                            
                            # move the file
                            $status=move_uploaded_file( $tmp, $targetpath );
                            
                            # upload the output variable
                            $uploads[]=$status ? sprintf('The file "%s" has been uploaded OK.<br />Information has been added to the directory: %s', $targetname, ( $dbstatus ? 'True' : 'False' ) ) : sprintf('There was a problem saving "%s".<br />Information logged to db: %s ',$targetname, ( $dbstatus ? 'True' : 'False' ) );
                            
                            # maintain a list of files to be used if db operation fails.
                            $files[]=$targetpath;
                            
                            
                            
                            # save image details... or try to
                            $stmt->execute();
                        }
                    }
                    
                    
                    
                    
                    
                    #commit to database or erase files if there is a problem
                    if( !$db->commit() ) {
                        $errors[]='Failed to commit transaction';
                        foreach( $files as $file ){
                            unlink( $file );
                            $errors[]=sprintf('File deleted: "%s"',$file);
                        }
                        $uploads=[];
                    }
                    
                }
            }
        }catch( Exception $e ){
            $errors[]=$e->getMessage();
        }
    }
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <title>PHP: Multiple file uploads - different inputs</title>
        <meta charset='utf-8' />
        <style>
            form{width:60%;float:none;margin:1rem auto;padding:0.5rem 1rem;font-family:monospace;border:1px dashed gray;border-radius:0.5rem;background:whitesmoke;}
            label{width:80%;margin:0.75rem auto;display:block;float:none;padding:0.25rem;}
            label > input{float:right;width:75%;}
            fieldset{margin:1rem auto;padding:1rem;border:1px solid rgba(100,100,100,0.5);background:white;border-radius:0.5rem;}
            form > div{margin:1rem auto}
            [type='submit']{padding:1rem;}
            [type='file']{border:1px solid rgba(100,100,100,0.5); padding:0.25rem;border-radius:0.25rem;color:rgba(100,100,100,0.5);background:rgba(200,200,200,0.5);}
            legend{background:rgba(100,100,100,0.5);color:white;padding:0.5rem;border-radius:0.5rem;min-width:20%;}     
            
            .error{color:red;}
            .success{color:green;}
        </style>
    </head>
    <body>
        <form name=uploads' method='post' enctype='multipart/form-data'>
            
            <fieldset>
                <legend>Product</legend>
                <label>Name:<input type='text' name='productname' /></label>
                <label>Brand:<input type='text' name='productbrand' /></label>
            </fieldset>
            
            <fieldset>
                <legend>Product images</legend>
                <label>Image-Face:<input type='file' name='productimage[FaceProduct]' /></label>
                <label>Image-Nutrition:<input type='file' name='productimage[NutritionValue]' /></label>
                <!-- other images could be added using same method but different index values ~ EG: -->
                <label>Image-Ingredients:<input type='file' name='productimage[Ingredients]' /></label>
                <label>Image-Labels:<input type='file' name='productimage[Labels]' /></label>
            </fieldset>
            
            <fieldset>
                <legend>User details</legend>
                <label>Added by:<input type='text' name='addername' /></label>
                <label>Email:<input type='text' name='adder_email' /></label>
            </fieldset>
            
            <fieldset>
                <input type='submit' />
            </fieldset>
            
            <div>
            <?php
                if( $_SERVER['REQUEST_METHOD']=='POST' ){
                    
                    if( !empty( $uploads ) ){
                        foreach( $uploads as $message )printf('<div class="success">%s</div>',$message);
                    }
                    if( !empty( $errors ) ){
                        foreach( $errors as $message )printf('<div class="error">%s</div>',$message);
                    }
                    
                    $errors=$uploads=array();
                }
            ?>
            </div>
        </form>
    </body>
</html>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM