jquery upload

Meadows of Heaven

厚积薄发

end: blogTitle 博客的标题和副标题

done 随笔-305  文章-65  评论-38 

end: blogStats

end: navigator 博客导航栏

end: header 头部

done

jQuery File Upload 单页面多实例的实现


jQuery File Upload 的 GitHub 地址:https://github.com/blueimp/jQuery-File-Upload

插件描述:jQuery File Upload 是一个 jQuery 图片上传组件,支持多文件上传、取消、删除,上传前缩略图预览、列表显示图片大小,支持上传进度条显示。插件基于开放的标准,如 HTML5 和 JavaScript ,不需要额外的浏览器插件(例如使用Adobe 的 Flash ),在旧版浏览器中使用 XMLHttpRequest 上传文件。(参见:http://www.jq22.com/jquery-info230)。

需求:在一个页面中包含多个插件实例。例如在生鲜电商网站后台的食谱添加/编辑页面,需要上传/编辑一道菜的食材和配料,就需要在页面中同时包含两个上传实例。插件的文档中有关于单页面多实例的介绍:Multiple File Upload Widgets on the same page,里面说明很简单,把 demo 中 index.html 的 form 表单的 id 改成 class,再简单修改 js/main.js 就可以了。

在很天真的试过之后,发现根本不是这么回事,index.html 中文件域的 name 是写死的,根本无法满足单页面多实例的需求,只能对插件进行修改...而且在改完之后发现修改的工作量很大。

代码是在 demo 的基础上,后端使用 php,删除了不需要的文件,比如其他后端语言处理程序。没有做数据验证和入库等处理,展示页面直接遍历文件夹读取文件。

最终效果图:

初始界面


 

上传图片及刷新页面


文件结构及主要修改文件


 

js


 

server


 

/index.html

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

<!DOCTYPE HTML>

<!--

/*

 * jQuery File Upload Plugin Demo 9.1.0

 * https://github.com/blueimp/jQuery-File-Upload

 *

 * Copyright 2010, Sebastian Tschan

 * https://blueimp.net

 *

 * Licensed under the MIT license:

 * http://www.opensource.org/licenses/MIT

 */

-->

<html lang="en">

<head>

<!-- Force latest IE rendering engine or ChromeFrame if installed -->

<!--[if IE]>

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

<![endif]-->

<meta charset="utf-8">

<title>jQuery File Upload Demo</title>

<meta name="description" content="File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<!-- Bootstrap styles -->

<link rel="stylesheet" href="css/bootstrap.min.css">

<!-- Generic page styles -->

<link rel="stylesheet" href="css/style.css">

<!-- blueimp Gallery styles -->

<link rel="stylesheet" href="css/blueimp-gallery.min.css">

<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->

<link rel="stylesheet" href="css/jquery.fileupload.css">

<!-- <link rel="stylesheet" href="css/jquery.fileupload-ui.css"> -->

<!-- CSS adjustments for browsers with JavaScript disabled -->

<noscript><link rel="stylesheet" href="css/jquery.fileupload-noscript.css"></noscript>

<noscript><link rel="stylesheet" href="css/jquery.fileupload-ui-noscript.css"></noscript>

</head>

<body>

<div class="container">

    <!-- The file upload form used as target for the file upload widget -->

    <form class="fileupload" action="server/php" method="POST" enctype="multipart/form-data">

        <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->

        <div class="row fileupload-buttonbar">

            <div class="col-lg-7">

                <!-- The fileinput-button span is used to style the file input field as button -->

                <span class="btn btn-primary">食材</span>

                <span class="btn btn-success fileinput-button">

                    <i class="glyphicon glyphicon-plus"></i>

                    <span>Add files...</span>

                    <input type="file" name="food[]" multiple>

                </span>

                <button type="submit" class="btn btn-primary start">

                    <i class="glyphicon glyphicon-upload"></i>

                    <span>Start upload</span>

                </button>

                <button type="reset" class="btn btn-warning cancel">

                    <i class="glyphicon glyphicon-ban-circle"></i>

                    <span>Cancel upload</span>

                </button>

                <button type="button" class="btn btn-danger delete">

                    <i class="glyphicon glyphicon-trash"></i>

                    <span>Delete</span>

                </button>

                <input type="checkbox" class="toggle">

                <!-- The global file processing state -->

                <span class="fileupload-process"></span>

            </div>

            <!-- The global progress state -->

            <div class="col-lg-5 fileupload-progress fade">

                <!-- The global progress bar -->

                <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">

                    <div class="progress-bar progress-bar-success" style="width:0%;"></div>

                </div>

                <!-- The extended global progress state -->

                <div class="progress-extended"> </div>

            </div>

        </div>

        <!-- The table listing the files available for upload/download -->

        <table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>    

    </form>

    <!-- Multiple File Upload Widgets on the same page -->

    <form class="fileupload" action="server/php" method="POST" enctype="multipart/form-data">

        <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->

        <div class="row fileupload-buttonbar">

            <div class="col-lg-7">

                <!-- The fileinput-button span is used to style the file input field as button -->

                <span class="btn btn-primary">配料</span>

                <span class="btn btn-success fileinput-button">

                    <i class="glyphicon glyphicon-plus"></i>

                    <span>Add files...</span>

                    <input type="file" name="batching[]" multiple>

                </span>

                <button type="submit" class="btn btn-primary start">

                    <i class="glyphicon glyphicon-upload"></i>

                    <span>Start upload</span>

                </button>

                <button type="reset" class="btn btn-warning cancel">

                    <i class="glyphicon glyphicon-ban-circle"></i>

                    <span>Cancel upload</span>

                </button>

                <button type="button" class="btn btn-danger delete">

                    <i class="glyphicon glyphicon-trash"></i>

                    <span>Delete</span>

                </button>

                <input type="checkbox" class="toggle">

                <!-- The global file processing state -->

                <span class="fileupload-process"></span>

            </div>

            <!-- The global progress state -->

            <div class="col-lg-5 fileupload-progress fade">

                <!-- The global progress bar -->

                <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">

                    <div class="progress-bar progress-bar-success" style="width:0%;"></div>

                </div>

                <!-- The extended global progress state -->

                <div class="progress-extended"> </div>

            </div>

        </div>

        <!-- The table listing the files available for upload/download -->

        <table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>    

    </form>

</div>

<!-- The blueimp Gallery widget -->

<div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls" data-filter=":even">

    <div class="slides"></div>

    <h3 class="title"></h3>

    <a class="prev">‹</a>

    <a class="next">›</a>

    <a class="close">×</a>

    <a class="play-pause"></a>

    <ol class="indicator"></ol>

</div>

<!-- The template to display files available for upload -->

<script id="template-upload" type="text/x-tmpl">

{% for (var i=0, file; file=o.files[i]; i++) { %}

    <tr class="template-upload fade">

        <td>

            <span class="preview"></span>

        </td>

        <td>

            <p class="name">{%=file.name%}</p>

            <strong class="error text-danger"></strong>

        </td>

        <td>

            <p class="size">Processing...</p>

            <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>

        </td>

        <td>

            {% if (!i && !o.options.autoUpload) { %}

                <button class="btn btn-primary start" disabled>

                    <i class="glyphicon glyphicon-upload"></i>

                    <span>Start</span>

                </button>

            {% } %}

            {% if (!i) { %}

                <button class="btn btn-warning cancel">

                    <i class="glyphicon glyphicon-ban-circle"></i>

                    <span>Cancel</span>

                </button>

            {% } %}

        </td>

    </tr>

{% } %}

</script>

<!-- The template to display files available for download -->

<script id="template-download" type="text/x-tmpl">

{% for (var i=0, file; file=o.files[i]; i++) { %}

    <tr class="template-download fade">

        <td>

            <span class="preview">

                {% if (file.thumbnailUrl) { %}

                    <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>

                {% } %}

            </span>

        </td>

        <td>

            <p class="name">

                {% if (file.url) { %}

                    <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>

                {% } else { %}

                    <span>{%=file.name%}</span>

                {% } %}

            </p>

            {% if (file.error) { %}

                <div><span class="label label-danger">Error</span> {%=file.error%}</div>

            {% } %}

        </td>

        <td>

            <span class="size">{%=o.formatFileSize(file.size)%}</span>

        </td>

        <td>

            {% if (file.deleteUrl) { %}

                <button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>

                    <i class="glyphicon glyphicon-trash"></i>

                    <span>Delete</span>

                </button>

                <input type="checkbox" name="delete" value="1" class="toggle">

            {% } else { %}

                <button class="btn btn-warning cancel">

                    <i class="glyphicon glyphicon-ban-circle"></i>

                    <span>Cancel</span>

                </button>

            {% } %}

        </td>

    </tr>

{% } %}

</script>

<script src="js/jquery/1.10.2/jquery.min.js"></script>

<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->

<script src="js/vendor/jquery.ui.widget.js"></script>

<!-- The Templates plugin is included to render the upload/download listings -->

<script src="js/tmpl.min.js"></script>

<!-- The Load Image plugin is included for the preview images and image resizing functionality -->

<script src="js/load-image.all.min.js"></script>

<!-- The Canvas to Blob plugin is included for image resizing functionality -->

<script src="js/canvas-to-blob.min.js"></script>

<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->

<script src="js/bootstrap/3.0.0/js/bootstrap.min.js"></script>

<!-- blueimp Gallery script -->

<script src="js/jquery.blueimp-gallery.min.js"></script>

<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->

<script src="js/jquery.iframe-transport.js"></script>

<!-- The basic File Upload plugin -->

<script src="js/jquery.fileupload.js"></script>

<!-- The File Upload processing plugin -->

<script src="js/jquery.fileupload-process.js"></script>

<!-- The File Upload image preview & resize plugin -->

<script src="js/jquery.fileupload-image.js"></script>

<!-- The File Upload audio preview plugin -->

<script src="js/jquery.fileupload-audio.js"></script>

<!-- The File Upload video preview plugin -->

<script src="js/jquery.fileupload-video.js"></script>

<!-- The File Upload validation plugin -->

<script src="js/jquery.fileupload-validate.js"></script>

<!-- The File Upload user interface plugin -->

<script src="js/jquery.fileupload-ui.js"></script>

<!-- The main application script -->

<script src="js/main.js"></script>

<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 -->

<!--[if (gte IE 8)&(lt IE 10)]>

<script src="js/cors/jquery.xdr-transport.js"></script>

<![endif]-->

</body>

<script>

    // $('.fileupload').fileupload({

    //     // Uncomment the following to send cross-domain cookies:

    //     //xhrFields: {withCredentials: true},

    //     url: 'server/php/?fields=shirt,sweater',

    // });

    var fields = 'food,batching';

    $('.fileupload').fileupload({

        url: 'server/php/?fields=' + fields,

        add: function (e, data) {

            // 不用点击直接上传

            var jqXHR = data.submit()

                .success(function (result, textStatus, jqXHR) {})

                .error(function (jqXHR, textStatus, errorThrown) {})

                .complete(function (result, textStatus, jqXHR) {});

        }    

    });

   

    $.ajax({

        url: 'server/php/?fields=' + fields,

        success(data) {

            var dataObj = JSON.parse(data);

            $.each(dataObj, function(name, value) {              

                $.each(value, function(k, v){

                    var item = '<tr class="template-download fade in">';

                    item += '<td><span class="preview"><a data-gallery="" download="' + v.name + '" title="' + v.name + '" href="' + v.url + '"><img src="' + v.thumbnailUrl + '"></a></span></td><td><p class="name"><a data-gallery="" download="' + v.name + '" title="' + v.url + '" href="' + v.url + '">' + v.name + '</a></p></td><td><span class="size">' + (v.size / 1000) + ' KB</span></td><td>';

             

                    item += '<button data-url="' + v.deleteUrl + '" data-type="' + v.deleteType + '" class="btn btn-danger delete" ><i class="glyphicon glyphicon-trash"></i><span>Delete</span></button>';

                    item += ' <input type="checkbox" class="toggle" value="1" name="delete"></td></tr>';

 

                    var $item = $(item);

                    $input_file = eval($("input[type='file'][name='" + name + "[]']"));

                    $item.appendTo($input_file.parents('.fileupload-buttonbar').siblings('.table-striped').children('.files'));                                        

                });                   

            });                     

        }

    });

</script>

</html>

说明:

通过 fields 来配置文件中不同的文件域,多个文件域的 name 用逗号 , 隔开。这是修改后 demo 中唯一需要根据页面文件域 name 的不同要做配置地方

1

var fields = 'food,batching';

  

/js/jquery.fileupload-ui.js

修改 $.widget('blueimp.fileupload', $.blueimp.fileupload, {}) 中 的 getFilesFromResponse

1

2

3

4

5

6

7

8

9

10

11

getFilesFromResponse: function (data) {

    var paramName = JSON.stringify(data.paramName);

    if(paramName) {

        var files = paramName.slice(2,-4);

    }

    // console.log(files,eval("data.result."+files));

    if (data.result && $.isArray(eval("data.result."+files))) {

        return eval("data.result."+files);

    }

    return [];

},

把写死的 files 改成页面中实际的 name

完整文件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703

704

705

706

707

708

709

/*

 * jQuery File Upload User Interface Plugin 9.6.0

 * https://github.com/blueimp/jQuery-File-Upload

 *

 * Copyright 2010, Sebastian Tschan

 * https://blueimp.net

 *

 * Licensed under the MIT license:

 * http://www.opensource.org/licenses/MIT

 */

 

/* jshint nomen:false */

/* global define, window */

 

(function (factory) {

    'use strict';

    if (typeof define === 'function' && define.amd) {

        // Register as an anonymous AMD module:

        define([

            'jquery',

            'tmpl',

            './jquery.fileupload-image',

            './jquery.fileupload-audio',

            './jquery.fileupload-video',

            './jquery.fileupload-validate'

        ], factory);

    } else {

        // Browser globals:

        factory(

            window.jQuery,

            window.tmpl

        );

    }

}(function ($, tmpl) {

    'use strict';

 

    $.blueimp.fileupload.prototype._specialOptions.push(

        'filesContainer',

        'uploadTemplateId',

        'downloadTemplateId'

    );

 

    // The UI version extends the file upload widget

    // and adds complete user interface interaction:

    $.widget('blueimp.fileupload', $.blueimp.fileupload, {

 

        options: {

            // By default, files added to the widget are uploaded as soon

            // as the user clicks on the start buttons. To enable automatic

            // uploads, set the following option to true:

            autoUpload: false,

            // The ID of the upload template:

            uploadTemplateId: 'template-upload',

            // The ID of the download template:

            downloadTemplateId: 'template-download',

            // The container for the list of files. If undefined, it is set to

            // an element with class "files" inside of the widget element:

            filesContainer: undefined,

            // By default, files are appended to the files container.

            // Set the following option to true, to prepend files instead:

            prependFiles: false,

            // The expected data type of the upload response, sets the dataType

            // option of the $.ajax upload requests:

            dataType: 'json',

             

            // Error and info messages:

            messages: {

                unknownError: 'Unknown error' 

            },

 

            // Function returning the current number of files,

            // used by the maxNumberOfFiles validation:

            getNumberOfFiles: function () {

                return this.filesContainer.children()

                    .not('.processing').length;

            },

 

            // Callback to retrieve the list of files from the server response:

            getFilesFromResponse: function (data) {

                var paramName = JSON.stringify(data.paramName);

                if(paramName) {

                    var files = paramName.slice(2,-4);

                }

                // console.log(files,eval("data.result."+files));

                if (data.result && $.isArray(eval("data.result."+files))) {

                    return eval("data.result."+files);

                }

                return [];

            },

 

            // The add callback is invoked as soon as files are added to the fileupload

            // widget (via file input selection, drag & drop or add API call).

            // See the basic file upload widget for more information:

            add: function (e, data) {

                if (e.isDefaultPrevented()) {

                    return false;

                }

                var $this = $(this),

                    that = $this.data('blueimp-fileupload') ||

                        $this.data('fileupload'),

                    options = that.options;

                data.context = that._renderUpload(data.files)

                    .data('data', data)

                    .addClass('processing');

                options.filesContainer[

                    options.prependFiles ? 'prepend' : 'append'

                ](data.context);

                that._forceReflow(data.context);

                that._transition(data.context);

                data.process(function () {

                    return $this.fileupload('process', data);

                }).always(function () {

                    data.context.each(function (index) {

                        $(this).find('.size').text(

                            that._formatFileSize(data.files[index].size)

                        );

                    }).removeClass('processing');

                    that._renderPreviews(data);

                }).done(function () {

                    data.context.find('.start').prop('disabled', false);

                    if ((that._trigger('added', e, data) !== false) &&

                            (options.autoUpload || data.autoUpload) &&

                            data.autoUpload !== false) {

                        data.submit();

                    }

                }).fail(function () {

                    if (data.files.error) {

                        data.context.each(function (index) {

                            var error = data.files[index].error;

                            if (error) {

                                $(this).find('.error').text(error);

                            }

                        });

                    }

                });

            },

            // Callback for the start of each file upload request:

            send: function (e, data) {

                if (e.isDefaultPrevented()) {

                    return false;

                }

                var that = $(this).data('blueimp-fileupload') ||

                        $(this).data('fileupload');

                if (data.context && data.dataType &&

                        data.dataType.substr(0, 6) === 'iframe') {

                    // Iframe Transport does not support progress events.

                    // In lack of an indeterminate progress bar, we set

                    // the progress to 100%, showing the full animated bar:

                    data.context

                        .find('.progress').addClass(

                            !$.support.transition && 'progress-animated'

                        )

                        .attr('aria-valuenow', 100)

                        .children().first().css(

                            'width',

                            '100%'

                        );

                }

                return that._trigger('sent', e, data);

            },

            // Callback for successful uploads:

            done: function (e, data) {

                if (e.isDefaultPrevented()) {

                    return false;

                }

                var that = $(this).data('blueimp-fileupload') ||

                        $(this).data('fileupload'),

                    getFilesFromResponse = data.getFilesFromResponse ||

                        that.options.getFilesFromResponse,

                    files = getFilesFromResponse(data),

                    template,

                    deferred;

                if (data.context) {

                    data.context.each(function (index) {

                        var file = files[index] ||

                                {error: 'Empty file upload result'};

                        deferred = that._addFinishedDeferreds();

                        that._transition($(this)).done(

                            function () {

                                var node = $(this);

                                template = that._renderDownload([file])

                                    .replaceAll(node);

                                that._forceReflow(template);

                                that._transition(template).done(

                                    function () {

                                        data.context = $(this);

                                        that._trigger('completed', e, data);

                                        that._trigger('finished', e, data);

                                        deferred.resolve();

                                    }

                                );

                            }

                        );

                    });

                } else {

                    template = that._renderDownload(files)[

                        that.options.prependFiles ? 'prependTo' : 'appendTo'

                    ](that.options.filesContainer);

                    that._forceReflow(template);

                    deferred = that._addFinishedDeferreds();

                    that._transition(template).done(

                        function () {

                            data.context = $(this);

                            that._trigger('completed', e, data);

                            that._trigger('finished', e, data);

                            deferred.resolve();

                        }

                    );

                }

            },

            // Callback for failed (abort or error) uploads:

            fail: function (e, data) {

                if (e.isDefaultPrevented()) {

                    return false;

                }

                var that = $(this).data('blueimp-fileupload') ||

                        $(this).data('fileupload'),

                    template,

                    deferred;               

                if (data.context) {

                    data.context.each(function (index) {

                        if (data.errorThrown !== 'abort') {

                            var file = data.files[index];

                            file.error = file.error || data.errorThrown ||

                                data.i18n('unknownError');

                            deferred = that._addFinishedDeferreds();

                            that._transition($(this)).done(

                                function () {

                                    var node = $(this);

                                    template = that._renderDownload([file])

                                        .replaceAll(node);

                                    that._forceReflow(template);

                                    that._transition(template).done(

                                        function () {

                                            data.context = $(this);

                                            that._trigger('failed', e, data);

                                            that._trigger('finished', e, data);

                                            deferred.resolve();

                                        }

                                    );

                                }

                            );

                        } else {

                            deferred = that._addFinishedDeferreds();

                            that._transition($(this)).done(

                                function () {

                                    $(this).remove();

                                    that._trigger('failed', e, data);

                                    that._trigger('finished', e, data);

                                    deferred.resolve();

                                }

                            );

                        }

                    });

                } else if (data.errorThrown !== 'abort') {

                    data.context = that._renderUpload(data.files)[

                        that.options.prependFiles ? 'prependTo' : 'appendTo'

                    ](that.options.filesContainer)

                        .data('data', data);

                    that._forceReflow(data.context);

                    deferred = that._addFinishedDeferreds();

                    that._transition(data.context).done(

                        function () {

                            data.context = $(this);

                            that._trigger('failed', e, data);

                            that._trigger('finished', e, data);

                            deferred.resolve();

                        }

                    );

                } else {

                    that._trigger('failed', e, data);

                    that._trigger('finished', e, data);

                    that._addFinishedDeferreds().resolve();

                }

            },

            // Callback for upload progress events:

            progress: function (e, data) {

                if (e.isDefaultPrevented()) {

                    return false;

                }

                var progress = Math.floor(data.loaded / data.total * 100);

                if (data.context) {

                    data.context.each(function () {

                        $(this).find('.progress')

                            .attr('aria-valuenow', progress)

                            .children().first().css(

                                'width',

                                progress + '%'

                            );

                    });

                }

            },

            // Callback for global upload progress events:

            progressall: function (e, data) {

                if (e.isDefaultPrevented()) {

                    return false;

                }

                var $this = $(this),

                    progress = Math.floor(data.loaded / data.total * 100),

                    globalProgressNode = $this.find('.fileupload-progress'),

                    extendedProgressNode = globalProgressNode

                        .find('.progress-extended');

                if (extendedProgressNode.length) {

                    extendedProgressNode.html(

                        ($this.data('blueimp-fileupload') || $this.data('fileupload'))

                            ._renderExtendedProgress(data)

                    );

                }

                globalProgressNode

                    .find('.progress')

                    .attr('aria-valuenow', progress)

                    .children().first().css(

                        'width',

                        progress + '%'

                    );

            },

            // Callback for uploads start, equivalent to the global ajaxStart event:

            start: function (e) {

                if (e.isDefaultPrevented()) {

                    return false;

                }

                var that = $(this).data('blueimp-fileupload') ||

                        $(this).data('fileupload');

                that._resetFinishedDeferreds();

                that._transition($(this).find('.fileupload-progress')).done(

                    function () {

                        that._trigger('started', e);

                    }

                );

            },

            // Callback for uploads stop, equivalent to the global ajaxStop event:

            stop: function (e) {

                if (e.isDefaultPrevented()) {

                    return false;

                }

                var that = $(this).data('blueimp-fileupload') ||

                        $(this).data('fileupload'),

                    deferred = that._addFinishedDeferreds();

                $.when.apply($, that._getFinishedDeferreds())

                    .done(function () {

                        that._trigger('stopped', e);

                    });

                that._transition($(this).find('.fileupload-progress')).done(

                    function () {

                        $(this).find('.progress')

                            .attr('aria-valuenow', '0')

                            .children().first().css('width', '0%');

                        $(this).find('.progress-extended').html(' ');

                        deferred.resolve();

                    }

                );

            },

            processstart: function (e) {

                if (e.isDefaultPrevented()) {

                    return false;

                }

                $(this).addClass('fileupload-processing');

            },

            processstop: function (e) {

                if (e.isDefaultPrevented()) {

                    return false;

                }

                $(this).removeClass('fileupload-processing');

            },

            // Callback for file deletion:

            destroy: function (e, data) {

                if (e.isDefaultPrevented()) {

                    return false;

                }       

                var that = $(this).data('blueimp-fileupload') ||

                        $(this).data('fileupload'),

                    removeNode = function () {

                        that._transition(data.context).done(

                            function () {

                                $(this).remove();

                                that._trigger('destroyed', e, data);

                            }

                        );

                    };

                if (data.url) {

                    data.dataType = data.dataType || that.options.dataType;

                    $.ajax(data).done(removeNode).fail(function () {

                        that._trigger('destroyfailed', e, data);

                    });

                } else {

                    removeNode();

                }

            }

        },

 

        _resetFinishedDeferreds: function () {

            this._finishedUploads = [];

        },

 

        _addFinishedDeferreds: function (deferred) {

            if (!deferred) {

                deferred = $.Deferred();

            }

            this._finishedUploads.push(deferred);

            return deferred;

        },

 

        _getFinishedDeferreds: function () {

            return this._finishedUploads;

        },

 

        // Link handler, that allows to download files

        // by drag & drop of the links to the desktop:

        _enableDragToDesktop: function () {

            var link = $(this),

                url = link.prop('href'),

                name = link.prop('download'),

                type = 'application/octet-stream';

            link.bind('dragstart', function (e) {

                try {

                    e.originalEvent.dataTransfer.setData(

                        'DownloadURL',

                        [type, name, url].join(':')

                    );

                } catch (ignore) {}

            });

        },

 

        _formatFileSize: function (bytes) {

            if (typeof bytes !== 'number') {

                return '';

            }

            if (bytes >= 1000000000) {

                return (bytes / 1000000000).toFixed(2) + ' GB';

            }

            if (bytes >= 1000000) {

                return (bytes / 1000000).toFixed(2) + ' MB';

            }

            return (bytes / 1000).toFixed(2) + ' KB';

        },

 

        _formatBitrate: function (bits) {

            if (typeof bits !== 'number') {

                return '';

            }

            if (bits >= 1000000000) {

                return (bits / 1000000000).toFixed(2) + ' Gbit/s';

            }

            if (bits >= 1000000) {

                return (bits / 1000000).toFixed(2) + ' Mbit/s';

            }

            if (bits >= 1000) {

                return (bits / 1000).toFixed(2) + ' kbit/s';

            }

            return bits.toFixed(2) + ' bit/s';

        },

 

        _formatTime: function (seconds) {

            var date = new Date(seconds * 1000),

                days = Math.floor(seconds / 86400);

            days = days ? days + 'd ' : '';

            return days +

                ('0' + date.getUTCHours()).slice(-2) + ':' +

                ('0' + date.getUTCMinutes()).slice(-2) + ':' +

                ('0' + date.getUTCSeconds()).slice(-2);

        },

 

        _formatPercentage: function (floatValue) {

            return (floatValue * 100).toFixed(2) + ' %';

        },

 

        _renderExtendedProgress: function (data) {

            return this._formatBitrate(data.bitrate) + ' | ' +

                this._formatTime(

                    (data.total - data.loaded) * 8 / data.bitrate

                ) + ' | ' +

                this._formatPercentage(

                    data.loaded / data.total

                ) + ' | ' +

                this._formatFileSize(data.loaded) + ' / ' +

                this._formatFileSize(data.total);

        },

 

        _renderTemplate: function (func, files) {

            if (!func) {

                return $();

            }

            var result = func({

                files: files,

                formatFileSize: this._formatFileSize,

                options: this.options

            });

            if (result instanceof $) {

                return result;

            }

            return $(this.options.templatesContainer).html(result).children();

        },

 

        _renderPreviews: function (data) {        

            data.context.find('.preview').each(function (index, elm) {

                $(elm).append(data.files[index].preview);

            });

        },

 

        _renderUpload: function (files) {

            return this._renderTemplate(

                this.options.uploadTemplate,

                files

            );

        },

 

        _renderDownload: function (files) {

            return this._renderTemplate(

                this.options.downloadTemplate,

                files

            ).find('a[download]').each(this._enableDragToDesktop).end();

        },

 

        _startHandler: function (e) {

            e.preventDefault();

            var button = $(e.currentTarget),

                template = button.closest('.template-upload'),

                data = template.data('data');

            button.prop('disabled', true);

            if (data && data.submit) {

                data.submit();

            }

        },

 

        _cancelHandler: function (e) {

            e.preventDefault();

            var template = $(e.currentTarget)

                    .closest('.template-upload,.template-download'),

                data = template.data('data') || {};

            data.context = data.context || template;

            if (data.abort) {

                data.abort();

            } else {

                data.errorThrown = 'abort';

                this._trigger('fail', e, data);

            }

        },

 

        _deleteHandler: function (e) {

            e.preventDefault();

            var button = $(e.currentTarget);

            this._trigger('destroy', e, $.extend({

                context: button.closest('.template-download'),

                type: 'DELETE'

            }, button.data()));

        },

 

        _forceReflow: function (node) {

            return $.support.transition && node.length &&

                node[0].offsetWidth;

        },

 

        _transition: function (node) {

            var dfd = $.Deferred();

            if ($.support.transition && node.hasClass('fade') && node.is(':visible')) {

                node.bind(

                    $.support.transition.end,

                    function (e) {

                        // Make sure we don't respond to other transitions events

                        // in the container element, e.g. from button elements:

                        if (e.target === node[0]) {

                            node.unbind($.support.transition.end);

                            dfd.resolveWith(node);

                        }

                    }

                ).toggleClass('in');

            } else {

                node.toggleClass('in');

                dfd.resolveWith(node);

            }

            return dfd;

        },

 

        _initButtonBarEventHandlers: function () {

            var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'),

                filesList = this.options.filesContainer;

            this._on(fileUploadButtonBar.find('.start'), {

                click: function (e) {

                    e.preventDefault();

                    filesList.find('.start').click();

                }

            });

            this._on(fileUploadButtonBar.find('.cancel'), {

                click: function (e) {

                    e.preventDefault();

                    filesList.find('.cancel').click();

                }

            });

            this._on(fileUploadButtonBar.find('.delete'), {

                click: function (e) {

                    e.preventDefault();

                    filesList.find('.toggle:checked')

                        .closest('.template-download')

                        .find('.delete').click();

                    fileUploadButtonBar.find('.toggle')

                        .prop('checked', false);

                }

            });

            this._on(fileUploadButtonBar.find('.toggle'), {

                change: function (e) {

                    filesList.find('.toggle').prop(

                        'checked',

                        $(e.currentTarget).is(':checked')

                    );

                }

            });

        },

 

        _destroyButtonBarEventHandlers: function () {

            this._off(

                this.element.find('.fileupload-buttonbar')

                    .find('.start, .cancel, .delete'),

                'click'

            );

            this._off(

                this.element.find('.fileupload-buttonbar .toggle'),

                'change.'

            );

        },

 

        _initEventHandlers: function () {

            this._super();

            this._on(this.options.filesContainer, {

                'click .start': this._startHandler,

                'click .cancel': this._cancelHandler,

                'click .delete': this._deleteHandler

            });

            this._initButtonBarEventHandlers();

        },

 

        _destroyEventHandlers: function () {

            this._destroyButtonBarEventHandlers();

            this._off(this.options.filesContainer, 'click');

            this._super();

        },

 

        _enableFileInputButton: function () {

            this.element.find('.fileinput-button input')

                .prop('disabled', false)

                .parent().removeClass('disabled');

        },

 

        _disableFileInputButton: function () {

            this.element.find('.fileinput-button input')

                .prop('disabled', true)

                .parent().addClass('disabled');

        },

 

        _initTemplates: function () {

            var options = this.options;

            options.templatesContainer = this.document[0].createElement(

                options.filesContainer.prop('nodeName')

            );

            if (tmpl) {

                if (options.uploadTemplateId) {

                    options.uploadTemplate = tmpl(options.uploadTemplateId);

                }

                if (options.downloadTemplateId) {

                    options.downloadTemplate = tmpl(options.downloadTemplateId);

                }

            }

        },

 

        _initFilesContainer: function () {

            var options = this.options;

            if (options.filesContainer === undefined) {

                options.filesContainer = this.element.find('.files');

            } else if (!(options.filesContainer instanceof $)) {

                options.filesContainer = $(options.filesContainer);

            }

        },

 

        _initSpecialOptions: function () {

            this._super();

            this._initFilesContainer();

            this._initTemplates();

        },

 

        _create: function () {

            this._super();

            this._resetFinishedDeferreds();

            if (!$.support.fileInput) {

                this._disableFileInputButton();

            }

        },

 

        enable: function () {

            var wasDisabled = false;

            if (this.options.disabled) {

                wasDisabled = true;

            }

            this._super();

            if (wasDisabled) {

                this.element.find('input, button').prop('disabled', false);

                this._enableFileInputButton();

            }

        },

 

        disable: function () {

            if (!this.options.disabled) {

                this.element.find('input, button').prop('disabled', true);

                this._disableFileInputButton();

            }

            this._super();

        }

 

    });

 

}));

  

./js/main.js

注释以下代码

1

2

3

4

5

$('.fileupload').fileupload({

    // Uncomment the following to send cross-domain cookies:

    //xhrFields: {withCredentials: true},

    url: 'server/php/'

});

移至 ./index.html 中

 

./server/php/index.php

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

<?php

/*

 * jQuery File Upload Plugin PHP Example 5.14

 * https://github.com/blueimp/jQuery-File-Upload

 *

 * Copyright 2010, Sebastian Tschan

 * https://blueimp.net

 *

 * Licensed under the MIT license:

 * http://www.opensource.org/licenses/MIT

 */

 

error_reporting(E_ALL | E_STRICT);

require('UploadHandler.php');

 

// 添加图片

if(! empty($_FILES)) {

    $keys = array_keys($_FILES);

    if(! empty($keys)) {

        $key = $keys[0];

    } else {

        $key = null;

    }

} else {

    // 删除图片时的参数

    $pathinfo = pathinfo($_SERVER['REQUEST_URI']);

    if(! empty($pathinfo['filename'])) {

        $dirname = preg_match('/^\?(.*)=.*$/', $pathinfo['filename'], $match);

        if(! empty($match[1]) && $match[1] != 'fields') {

            $key = $match[1];

        } else {

            $key = null;

        }

    }   else {

        $key = null;

    }

}

 

$upload_handler = new UploadHandler($key);

根据不同的添加/删除的不同情况,传递不同的参数,同时在页面加载时通过 ajax 获取不同文件夹的文件用于展示(并没有做多层目录或者文件存储目录与文件域的 name 不同的情况的考虑,同时实际项目的 url 模式也有可能与程序中的正则表达式不匹配,可在实际项目中根据实际情况修改)

 

./server/php/UploadHandler.php 上传类

修改了 $this->options 中关于上传路径的参数,原 demo 中是写死的

1

2

3

4

5

6

7

8

9

10

11

12

function __construct($dir = null, $options = null, $initialize = true, $error_messages = null) {

    if($dir === null) {

        $dir = 'files';

    }

    $this->options = array(

        'script_url' => $this->get_full_url().'/',

        'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/'.$dir.'/',

        'upload_url' => $this->get_full_url().'/'.$dir.'/',

        'user_dirs' => false,

        'mkdir_mode' => 0755,

        'param_name' => $dir,

        ..........

  

修改了 get_singular_param_name 方法

1

2

3

4

protected function get_singular_param_name() {

    // return substr($this->options['param_name'], 0, -1);

    return $this->options['param_name'];

}

 

修改了 get 方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

public function get($print_response = true) {

    if ($print_response && isset($_GET['download'])) {

        return $this->download();

    }

 

    if(isset($_GET['fields']) && $_GET['fields'] != '') {

        $fields = $_GET['fields'];

        if(strpos($fields, ',') === false) { // 只有一个实例

            $this->options['upload_dir'] = dirname($this->get_server_var('SCRIPT_FILENAME')).'/'.$fields.'/';

            $this->options['upload_url'] = $this->get_full_url().'/'.$fields.'/';

            $this->options['param_name'] = $fields;

 

            $response = array(

                $val => $this->get_file_objects()

            );

            $return = $this->generate_response($response, $print_response);

        } else { // 多个实例

            $fields = explode(',', $fields);

            $return = array();

            foreach($fields as $key => $val) {

 

                $this->options['upload_dir'] = dirname($this->get_server_var('SCRIPT_FILENAME')).'/'.$val.'/';

                $this->options['upload_url'] = $this->get_full_url().'/'.$val.'/';

                $this->options['param_name'] = $val;

 

                $response = $this->get_file_objects();

                if(! empty($response)) {

                    $return[$val] = $response;

                }

            }

        }

        echo json_encode($return);

    }

}

get 方法主要用于刷新页面后展示之前的上传列表,这个只是最简单的实现,实际项目中应该是通过数据库查找

完整文件:

+ View Code

  

 GitHub 地址: https://github.com/dee0912/jquery_file_upload_multipart


分类: jQuery / jQuery UI,PHP

标签: jQuery File Upload, 上传插件

好文要顶 关注我 收藏该文 


黄棣-dee

关注 - 6

粉丝 - 28



+加关注

0

0




« 上一篇:PHP 字符串的隐式转换规则以及针对包含字母的字符串的递增/递减操作

» 下一篇:PHP 数组的拷贝是按值传递 or 按引用传递

posted @ 2016-06-17 00:30 黄棣-dee 阅读(1266) 评论(0) 编辑 收藏

end: topics 文章、评论容器



刷新评论刷新页面返回顶部

注册用户登录后才能发表评论,请 登录注册访问网站首页。


【推荐】50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库

【活动】优达学城正式发布“无人驾驶车工程师”课程

【推荐】移动直播百强八成都在用融云即时通讯云

【推荐】别再闷头写代码!找对工具,事半功倍,全能开发工具包用起来

【福利】网易云信1周年接入开发者突破10万,送红包活动火热开展中



最新IT新闻:

· 奥沙利文用VR打台球 摔了个大跟斗

· 苹果拟申请新商标,Magic Toolbar是什么来头?

· 东京工程师欲打造飞行汽车点燃奥运圣火

· 为什么美国断网?下一个会是中国吗?

· Win手机暴跌? 微软:我很赞同 Surface也是!

» 更多新闻...


最新知识库文章:

· 陈皓:什么是工程师文化?

· 没那么难,谈CSS的设计模式

· 程序猿媳妇儿注意事项

· 可是姑娘,你为什么要编程呢?

· 知其所以然(以算法学习为例)

» 更多知识库文章...


end: forFlow

end: mainContent 主体内容容器

done

公告

昵称:黄棣-dee

园龄:3年4个月

粉丝:28

关注:6

+加关注

<

2016年10月

>

25

26

27

28

29

30

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

1

2

3

4

5

搜索

 

常用链接

最新随笔

我的标签

随笔分类(277)

随笔档案(305)

文章档案(6)

积分与排名

  • 积分 - 29808
  • 排名 - 8141

最新评论

阅读排行榜

评论排行榜

推荐排行榜

end: sideBarMain

end: sideBar 侧边栏容器


end: main


done Copyright ©2016 黄棣-dee

end: footer

end: home 自定义的最大容器 PageEndHtml Block Begin

访客数: 

2016/05/17 起统计

PageEndHtml Block End 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值