/
writer.go
123 lines (104 loc) · 3.11 KB
/
writer.go
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
package sqlitefs
import (
"database/sql"
"mime"
"path/filepath"
)
const fragmentSize = 16 * 1024 // 16 КБ
type SQLiteWriter struct {
db *sql.DB
path string
buffer []byte
fragmentSize int
fragmentIndex int
fileID int
}
func NewSQLiteWriter(db *sql.DB, path string) *SQLiteWriter {
return &SQLiteWriter{
db: db,
path: path,
fragmentSize: fragmentSize,
buffer: make([]byte, 0, fragmentSize),
}
}
func (w *SQLiteWriter) Write(p []byte) (n int, err error) {
n = len(p)
startIndex := 0
for startIndex < n {
// Определяем, сколько данных можно добавить в буфер
remainingSpace := w.fragmentSize - len(w.buffer)
endIndex := min(n, startIndex+remainingSpace)
// Добавляем часть данных p в буфер
w.buffer = append(w.buffer, p[startIndex:endIndex]...)
// Проверяем, нужно ли записать фрагмент
if len(w.buffer) == w.fragmentSize {
err = w.writeFragment()
if err != nil {
return startIndex, err
}
}
startIndex = endIndex
}
// Если все данные записаны и буфер пуст, создаем запись файла
if len(w.buffer) == 0 && w.fragmentIndex == 0 {
err = w.createFileRecord()
if err != nil {
return n, err
}
}
return n, nil
}
func (w *SQLiteWriter) writeFragment() error {
// Проверка на наличие файла в базе данных и создание записи, если необходимо
if w.fragmentIndex == 0 {
err := w.createFileRecord()
if err != nil {
return err
}
}
// Запись фрагмента файла
_, err := w.db.Exec("INSERT INTO file_fragments (file_id, fragment_index, fragment) VALUES (?, ?, ?)", w.fileID, w.fragmentIndex, w.buffer)
if err != nil {
return err
}
// Очистка буфера и увеличение индекса фрагмента
w.buffer = w.buffer[:0]
w.fragmentIndex++
return nil
}
func (w *SQLiteWriter) createFileRecord() error {
// Определение MIME-типа файла
ext := filepath.Ext(w.path)
mimeType := mime.TypeByExtension(ext)
if mimeType == "" {
mimeType = "application/octet-stream" // Значение по умолчанию
}
// Проверка наличия записи файла в базе данных по пути файла
var fileID int64
err := w.db.QueryRow("SELECT id FROM file_metadata WHERE path = ?", w.path).Scan(&fileID)
if err == sql.ErrNoRows {
// Создание новой записи файла
result, err := w.db.Exec("INSERT INTO file_metadata (path, type) VALUES (?, ?)", w.path, mimeType)
if err != nil {
return err
}
fileID, err = result.LastInsertId()
if err != nil {
return err
}
} else if err != nil {
return err
}
w.fileID = int(fileID)
return nil
}
func (w *SQLiteWriter) Close() error {
if len(w.buffer) > 0 || w.fragmentIndex == 0 {
// Запись оставшегося буфера как последнего фрагмента
err := w.writeFragment()
if err != nil {
return err
}
}
return nil
}